import { ITotpInfo, TotpItem} from "../../biz/totp-info"
import { TOTP } from "../../bcat/totp"

export interface ShowTotpInfo {
  id: string;
  issuer: string;
  accountName: string;
  code: string;
  leftTime: {value: number, percent: number};
  period: number; 
  description:string;
}

class DataItem {
  leftTime : number;
  code: string;
  totpHandler: TOTP;
  constructor() {
  }

  static from(leftTime:number, code: string, totpHandler:TOTP): DataItem {
    let result = new DataItem();
    result.leftTime = leftTime;
    result.code = code;
    result.totpHandler = totpHandler;
    return result;
  }
  updateCode(seconds: number) {
    this.code = this.totpHandler.at(seconds);
  }
  updateLeftTime(seconds: number, period: number) {
    this.leftTime = period - seconds % period;
  }
}


export class ListPage {
  totpInfos: ITotpInfo;
  
  sec_now: number; //seconds
  totpData: Map<string, DataItem>;

  constructor(totpInfos: ITotpInfo) {
    this.totpInfos = totpInfos;

    this.sec_now = this.getSecondsFromDate(new Date());

    this.totpData = new Map();
    this.createData(this.sec_now);
  }
  private updateLeftTime(seconds: number, period: number): number {
    return period - seconds % period;
  }
  private createItem(seconds: number, totpItem: TotpItem): DataItem {
    let totpHandler = new TOTP(totpItem.data.secret);
    return DataItem.from(
      this.updateLeftTime(seconds, totpItem.data.period),
      totpHandler.at(seconds),
      totpHandler
    );
  }
  private createData(seconds: number) {
    this.totpData.clear();
    for( const [key, value] of this.totpInfos)  {
      if(value !== undefined){
        this.totpData.set(key, this.createItem(seconds, value));
        console.debug(`page.totpData item:[${key}] created`);
      }
      else{
        console.error(`item[${key}] not exists in totpInfos`);
      }
    }
  }


  private getSecondsFromDate(date: Date): number {
    return Math.floor(date.getTime()/1000);
  }
  updateTimestamp() {
    this.sec_now = this.getSecondsFromDate(new Date());

    for( const [key, value] of this.totpInfos){
      if(value !== undefined){
        let item = this.totpData.get(key);
        if(item !== undefined) {
          const period = value.data.period;
          item.updateLeftTime(this.sec_now, period);
          console.debug("updateLeftTime: ", item.leftTime)

          if((this.sec_now % value.data.period) == 0) {
            item.updateCode(this.sec_now);
            console.debug("updateCode: ", item.code)
          }
        }
        else{
          console.error(`totpData[${key}] not exists`);
        }
      }
      else{
        console.error(`item[${key}] not exists in totpInfos`);
      }
    }
  }

  getDescription(description: string){
    return (description !== undefined) && description.length > 0 ? description : '';
  }

  toShowInfo(): ShowTotpInfo[] {
    const mapDataArray: ShowTotpInfo[] = [];
    for( const [key, value] of this.totpInfos){
      if(value !== undefined){
        const item = this.totpData.get(key);
        if(item != undefined){
          mapDataArray.push({
            id: key,
            issuer:value.data.issuer,
            accountName: value.data.accountName,
            code: item.code,
            leftTime:{ 
               value: item.leftTime, 
               percent:Math.floor(item.leftTime*100/value.data.period),
             },
            period: value.data.period,
            description: this.getDescription(value.data.description),
          });
        }
        else{
          console.error(`totpData[${key}] not exists`);
        }
      }
      else{
        console.error(`item[${key}] not exists in totpInfos`);
      }
    };
    return mapDataArray;
  }
}

